#include<iostream>
#include <netinet/in.h>
#include<sys/socket.h>
#include<string>
#include<cstring>
#include<stdlib.h>
#include <arpa/inet.h>
#include<sys/wait.h>
#include<unistd.h>
const int num = 10;
#define PORT 8888
#define IP "0.0.0.0"
enum
{
    SOCKETERR = 1,
    BINDERR,
    LISTENERR
};
class TcpService;

class ThreadDate
{
public:
    ThreadDate(const uint16_t&port,const std::string&ip,int fd,TcpService*tptr)
    :_port(port)
    ,_ip(ip)
    ,_fd(fd)
    ,_tptr(tptr)
    {}
    uint16_t _port;
    std::string _ip;
    int _fd;
    TcpService*_tptr;
};

class TcpService
{
public:
    TcpService(uint16_t port=PORT,const std::string&ip=IP)
    :_port(port),_ip(ip)
    {

    }
    void Init()
    {
        //1:创建套接字；
        _listenfd = socket(AF_INET,SOCK_STREAM,0);
        if( _listenfd<0)
        {
            std::cout<<"socket fail"<<std::endl;
            exit(SOCKETERR);
        }
        std::cout<<"create socket success"<<":sockfd="<< _listenfd<<std::endl;
        //2:bind socket;
        struct sockaddr_in service;
        memset(&service,0,sizeof(service));
        service.sin_family = AF_INET;
        service.sin_port = htons(_port);//主机转网络；
        inet_aton(_ip.c_str(),&service.sin_addr);
        int n = bind(_listenfd,(const sockaddr*)&service,sizeof(service));
        if(n != 0)
        {
            std::cout<<"bind fail"<<std::endl;
            exit(BINDERR);
        }
        std::cout<<"bind success"<<std::endl;
        //3：tcp面向字节流需要连接的；
       n =  listen( _listenfd,num);
       if(n!=0)
       {
        std::cout<<"listen fail"<<std::endl;
        exit(LISTENERR);
       }

    }
    void Service(int fd,uint16_t clientport,const std::string clientip)
    {
        char buff[4096];
        while(true)
        {
            int n = read(fd,buff,sizeof(buff));
            if(n>0)
            {
                buff[n] = '\0';
                std::cout<<"client say#"<<buff<<std::endl;
                write(fd,buff,strlen(buff));
            }
            else if(n == 0)
            {
                break;
            }
        }
    }
    void start()
    {
        while(true)
        {
            std::cout<<"run"<<std::endl;
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            int sockfd = accept(_listenfd,(sockaddr*)&client,&len);
            uint16_t clientport = ntohs(client.sin_port);
            char clientip[32];
            inet_ntop(AF_INET,&client.sin_addr,clientip,len);
            std::cout<<"port:"<<clientport<<"clientip:"<<clientip<<std::endl;
            //1.单进程版本；
            // Service(sockfd,clientport,clientip);
            //2.多进程版本；
            // pid_t pid = fork();
            // if(pid == 0)
            // {
            //     close(_listenfd);
            //     //child process;
            //     if(fork()>0)
            //     {
            //         exit(0);
            //     }
            //     Service(sockfd,clientport,clientip);
            //     close(sockfd);
            //     exit(0);
            // }
            // close(sockfd);
            // waitpid(pid,nullptr,0);
            //3.多线程版本；
            ThreadDate*tp = new ThreadDate(clientport,clientip,sockfd,this);
            pthread_t tid;
            pthread_create(&tid,nullptr,handler,tp);
            
        }
    }
    static void*handler(void*args)
    {
        pthread_detach(pthread_self());
        ThreadDate*ps = static_cast<ThreadDate*>(args);
        ps->_tptr->Service(ps->_fd,ps->_port,ps->_ip);
        return nullptr;
    }
private:
    int _listenfd;
    uint16_t _port;
    std::string _ip;
};